package cn.demoncat.util.mongo.dao;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.bson.Document;
import org.bson.conversions.Bson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.index.Index;
import org.springframework.data.mongodb.core.index.IndexInfo;
import org.springframework.data.mongodb.core.index.IndexOperations;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component;

import com.mongodb.BasicDBObject;
import com.mongodb.client.MongoCollection;

import cn.demoncat.util.lang.entity.MapSo;
import cn.demoncat.util.mongo.util.IndexUtil;
import cn.demoncat.util.mongo.util.QueryUtil;

/**
 * MongoDB客户端管理
 * 
 * @author 延晓磊
 *
 * @since 2017年7月22日
 */
@Component
public class MongoAdminDao {

	/**
	 * Spring Data MongoDB
	 */
	@Autowired
	private MongoTemplate mongoTemplate;

	/**
	 * 获取所有集合的名称
	 *
	 * @author 延晓磊
	 *
	 * @since 2017年7月22日
	 */
	public Set<String> collectionNames() {
		return mongoTemplate.getCollectionNames();
	}

	/**
	 * 获取指定集合的名称
	 * 
	 * @param collection 集合映射类
	 * @return 集合名称
	 *
	 * @author 延晓磊
	 *
	 * @since 2017年7月22日
	 */
	public String collectionName(Class<?> collection) {
		return mongoTemplate.getCollectionName(collection);
	}

	/**
	 * 判断指定集合是否存在
	 * 
	 * @param collection 集合名
	 * @return 存在返回true
	 *
	 * @author 延晓磊
	 *
	 * @since 2017年7月22日
	 */
	public boolean collectionExist(String collection) {
		return mongoTemplate.collectionExists(collection);
	}

	/**
	 * 清空指定集合
	 * 
	 * @param collection 集合名
	 *
	 * @author 延晓磊
	 *
	 * @since 2017年7月22日
	 */
	public void dropCollection(String collection) {
		mongoTemplate.dropCollection(collection);
	}

	/**
	 * 执行MongoDB命令
	 * 
	 * @param jsonCommand JSON格式的命令语句
	 * 
	 * @return 执行结果
	 *
	 * @author 延晓磊
	 *
	 * @since 2017年7月22日
	 */
	public Document execute(String jsonCommand) {
		return mongoTemplate.executeCommand(jsonCommand);
	}

	/**
	 * 执行MongoDB的数据库命令
	 * 
	 * @param dbCommand  数据库命令
	 * @return 执行结果
	 *
	 * @author 延晓磊
	 *
	 * @since 2017年7月22日
	 */
	public Document executeDb(Bson dbCommand) {
		return mongoTemplate.getDb().runCommand(dbCommand);
	}

	/**
	 * 获取集合操作器：db.colName，不存在时创建
	 * 
	 * @param collectionClass	集合类
	 * 
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年1月23日
	 */
	public MongoCollection<Document> getCollection(String collectionClass){
		return mongoTemplate.getCollection(collectionClass);
	}
	
	/**
	 * 获取索引操作器
	 * 
	 * @param collectionClass	集合类
	 *
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2017年7月22日
	 */
	public IndexOperations indexOps(String collectionClass){
		return mongoTemplate.indexOps(collectionClass);
	}
	
	/**
	 * 删除所有索引
	 * 
	 * @param collectionClass	集合类
	 *
	 * @author 延晓磊
	 *
	 * @since 2017年7月22日
	 */
	public void dropAllIndexes(String collectionClass){
		this.indexOps(collectionClass).dropAllIndexes();
	}
	
	/**
	 * 删除指定索引
	 * 
	 * @param collectionClass	集合类
	 * @param indexName 索引名称
	 *
	 * @author 延晓磊
	 *
	 * @since 2017年7月22日
	 */
	public void dropIndex(String collectionClass, String indexName){
		this.indexOps(collectionClass).dropIndex(indexName);
	}
	
	/**
	 * 获取所有索引信息
	 * 
	 * @param collectionClass	集合类
	 * 
	 * @return List<IndexInfo> IndexInfo包含索引的域、索引名称、是否唯一等信息
	 * 
	 * @author 延晓磊
	 *
	 * @since 2017年7月22日
	 */
	public List<IndexInfo> getIndexInfo(String collectionClass){
		return this.indexOps(collectionClass).getIndexInfo();
	}
	
	/**
	 * 添加索引(单域索引/复合索引)
	 * 
	 * @param collectionClass	集合类
	 * @param index 索引
	 *
	 * @author 延晓磊
	 *
	 * @since 2017年7月22日
	 */
	public void addIndex(String collectionClass, Index index){
		this.indexOps(collectionClass).ensureIndex(index);
	}
	
	/**
	 * 统计
	 * 
	 * @param collection
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年8月31日
	 */
	public long count(String collection) {
		return mongoTemplate.getCollection(collection).countDocuments();
	}
	
	/**
	 * 统计
	 * 
	 * @param collection
	 * @param query
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年8月31日
	 */
	public long count(String collection,Map<String, Object> query) {
		return mongoTemplate.getCollection(collection).countDocuments(new BasicDBObject(query));
	}
	
	/**
	 * 统计
	 * 
	 * @param collection
	 * @param query
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年8月31日
	 */
	public long count(String collection,Query query) {
		return mongoTemplate.count(query, collection);
	}
	
	/**
	 * 分页查询
	 * 
	 * @param collection	集合
	 * @param condition		条件
	 * @param sort			仿SQL排序
	 * @param pageNum		当前页
	 * @param pageSize		页长
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年8月31日
	 */
	public List<MapSo> find(String collection,Map<String, Object> condition, Sort sort,int pageNum,int pageSize) {
		// 查询条件
		Query query = QueryUtil.build(QueryUtil.kvsQuery(condition), QueryUtil.getPageRequest(pageNum, pageSize), sort);
		// 查询
		return mongoTemplate.find(query, MapSo.class, collection);
	}
	
	/**
	 * 分页查询
	 * 
	 * @param collection	集合
	 * @param condition		条件
	 * @param sort			仿SQL排序
	 * @param pageNum		当前页
	 * @param pageSize		页长
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年8月31日
	 */
	public List<MapSo> find(String collection,Map<String, Object> condition, LinkedHashMap<String, Integer> sort,int pageNum,int pageSize) {
		// 查询条件
		Query query = QueryUtil.build(QueryUtil.kvsQuery(condition), QueryUtil.getPageRequest(pageNum, pageSize), QueryUtil.getSort(sort));
		// 查询
		return mongoTemplate.find(query, MapSo.class, collection);
	}
	
	/**
	 * 分页查询
	 * 
	 * @param collection	集合
	 * @param condition		条件
	 * @param pageNum		当前页
	 * @param pageSize		页长
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年8月31日
	 */
	public List<MapSo> find(String collection,Map<String, Object> condition, int pageNum,int pageSize) {
		// 查询条件
		Query query = QueryUtil.build(QueryUtil.kvsQuery(condition), QueryUtil.getPageRequest(pageNum, pageSize));
		// 查询
		return mongoTemplate.find(query, MapSo.class, collection);
	}
	/**
	 * ID删除
	 * 
	 * @param collection
	 * @param id
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年8月31日
	 */
	public void delete(String collection, String id) {
		mongoTemplate.remove(QueryUtil.idQuery(id), collection);
	}
	/**
	 * ID删除
	 * 
	 * @param collection
	 * @param id
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年8月31日
	 */
	public void delete(String collection, Long id) {
		mongoTemplate.remove(QueryUtil.idQuery(id), collection);
	}
	/**
	 * IDs删除
	 * 
	 * @param collection
	 * @param ids
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年8月31日
	 */
	public void delete(String collection, List<String> ids) {
		mongoTemplate.remove(QueryUtil.idsQuery(ids), collection);
	}
	/**
	 * 条件删除
	 * 
	 * @param collection
	 * @param condition
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年8月31日
	 */
	public void delete(String collection, Map<String, Object> condition) {
		mongoTemplate.remove(QueryUtil.kvsQuery(condition), collection);
	}
	
	/**
	 * 插入和更新（id重复）
	 * 
	 * @param collection
	 * @param obj
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年8月31日
	 */
	public void save(String collection,Object obj) {
		mongoTemplate.save(obj, collection);
	}
}
